{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Transformers installation\n",
    "! pip install transformers datasets evaluate accelerate\n",
    "# To install from source instead of the last release, comment the command above and uncomment the following one.\n",
    "# ! pip install git+https://github.com/huggingface/transformers.git"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Modelos multilinguísticos para inferência"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Existem vários modelos multilinguísticos no 🤗 Transformers e seus usos para inferência diferem dos modelos monolíngues.\n",
    "No entanto, nem *todos* os usos dos modelos multilíngues são tão diferentes.\n",
    "Alguns modelos, como o [google-bert/bert-base-multilingual-uncased](https://huggingface.co/google-bert/bert-base-multilingual-uncased),\n",
    "podem ser usados como se fossem monolíngues. Este guia irá te ajudar a usar modelos multilíngues cujo uso difere\n",
    "para o propósito de inferência."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## XLM"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "O XLM tem dez checkpoints diferentes dos quais apenas um é monolíngue.\n",
    "Os nove checkpoints restantes do modelo são subdivididos em duas categorias:\n",
    "checkpoints que usam de language embeddings e os que não."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### XLM com language embeddings"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Os seguintes modelos de XLM usam language embeddings para especificar a linguagem utilizada para a inferência.\n",
    "\n",
    "- `FacebookAI/xlm-mlm-ende-1024` (Masked language modeling, English-German)\n",
    "- `FacebookAI/xlm-mlm-enfr-1024` (Masked language modeling, English-French)\n",
    "- `FacebookAI/xlm-mlm-enro-1024` (Masked language modeling, English-Romanian)\n",
    "- `FacebookAI/xlm-mlm-xnli15-1024` (Masked language modeling, XNLI languages)\n",
    "- `FacebookAI/xlm-mlm-tlm-xnli15-1024` (Masked language modeling + translation, XNLI languages)\n",
    "- `FacebookAI/xlm-clm-enfr-1024` (Causal language modeling, English-French)\n",
    "- `FacebookAI/xlm-clm-ende-1024` (Causal language modeling, English-German)\n",
    "\n",
    "Os language embeddings são representados por um tensor de mesma dimensão que os `input_ids` passados ao modelo.\n",
    "Os valores destes tensores dependem do idioma utilizado e se identificam pelos atributos `lang2id` e `id2lang` do tokenizador.\n",
    "\n",
    "Neste exemplo, carregamos o checkpoint `FacebookAI/xlm-clm-enfr-1024`(Causal language modeling, English-French):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "from transformers import XLMTokenizer, XLMWithLMHeadModel\n",
    "\n",
    "tokenizer = XLMTokenizer.from_pretrained(\"FacebookAI/xlm-clm-enfr-1024\")\n",
    "model = XLMWithLMHeadModel.from_pretrained(\"FacebookAI/xlm-clm-enfr-1024\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "O atributo `lang2id` do tokenizador mostra os idiomas deste modelo e seus ids:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'en': 0, 'fr': 1}"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "print(tokenizer.lang2id)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Em seguida, cria-se um input de exemplo:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "input_ids = torch.tensor([tokenizer.encode(\"Wikipedia was used to\")])  # batch size of 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Estabelece-se o id do idioma, por exemplo `\"en\"`, e utiliza-se o mesmo para definir a language embedding.\n",
    "A language embedding é um tensor preenchido com `0`, que é o id de idioma para o inglês.\n",
    "Este tensor deve ser do mesmo tamanho que os `input_ids`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "language_id = tokenizer.lang2id[\"en\"]  # 0\n",
    "langs = torch.tensor([language_id] * input_ids.shape[1])  # torch.tensor([0, 0, 0, ..., 0])\n",
    "\n",
    "# We reshape it to be of size (batch_size, sequence_length)\n",
    "langs = langs.view(1, -1)  # is now of shape [1, sequence_length] (we have a batch size of 1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Agora você pode passar os `input_ids` e a language embedding ao modelo:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "outputs = model(input_ids, langs=langs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "O script [run_generation.py](https://github.com/huggingface/transformers/tree/master/examples/pytorch/text-generation/run_generation.py) pode gerar um texto com language embeddings utilizando os checkpoints `xlm-clm`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### XLM sem language embeddings"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Os seguintes modelos XLM não requerem o uso de language embeddings durante a inferência:\n",
    "\n",
    "- `FacebookAI/xlm-mlm-17-1280` (Modelagem de linguagem com máscara, 17 idiomas)\n",
    "- `FacebookAI/xlm-mlm-100-1280` (Modelagem de linguagem com máscara, 100 idiomas)\n",
    "\n",
    "Estes modelos são utilizados para representações genéricas de frase diferentemente dos checkpoints XLM anteriores."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## BERT"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Os seguintes modelos do BERT podem ser utilizados para tarefas multilinguísticas:\n",
    "\n",
    "- `google-bert/bert-base-multilingual-uncased` (Modelagem de linguagem com máscara + Previsão de frases, 102 idiomas)\n",
    "- `google-bert/bert-base-multilingual-cased` (Modelagem de linguagem com máscara + Previsão de frases, 104 idiomas)\n",
    "\n",
    "Estes modelos não requerem language embeddings durante a inferência. Devem identificar a linguagem a partir\n",
    "do contexto e realizar a inferência em sequência."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## XLM-RoBERTa"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Os seguintes modelos do XLM-RoBERTa podem ser utilizados para tarefas multilinguísticas:\n",
    "\n",
    "- `FacebookAI/xlm-roberta-base` (Modelagem de linguagem com máscara, 100 idiomas)\n",
    "- `FacebookAI/xlm-roberta-large` Modelagem de linguagem com máscara, 100 idiomas)\n",
    "\n",
    "O XLM-RoBERTa foi treinado com 2,5 TB de dados do CommonCrawl recém-criados e testados em 100 idiomas.\n",
    "Proporciona fortes vantagens sobre os modelos multilinguísticos publicados anteriormente como o mBERT e o XLM em tarefas\n",
    "subsequentes como a classificação, a rotulagem de sequências e à respostas a perguntas."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## M2M100"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Os seguintes modelos de M2M100 podem ser utilizados para traduções multilinguísticas:\n",
    "\n",
    "- `facebook/m2m100_418M` (Tradução)\n",
    "- `facebook/m2m100_1.2B` (Tradução)\n",
    "\n",
    "Neste exemplo, o checkpoint `facebook/m2m100_418M` é carregado para traduzir do mandarim ao inglês. É possível\n",
    "estabelecer o idioma de origem no tokenizador:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import M2M100ForConditionalGeneration, M2M100Tokenizer\n",
    "\n",
    "en_text = \"Do not meddle in the affairs of wizards, for they are subtle and quick to anger.\"\n",
    "chinese_text = \"不要插手巫師的事務, 因為他們是微妙的, 很快就會發怒.\"\n",
    "\n",
    "tokenizer = M2M100Tokenizer.from_pretrained(\"facebook/m2m100_418M\", src_lang=\"zh\")\n",
    "model = M2M100ForConditionalGeneration.from_pretrained(\"facebook/m2m100_418M\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tokenização do texto:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "encoded_zh = tokenizer(chinese_text, return_tensors=\"pt\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "O M2M100 força o id do idioma de destino como o primeiro token gerado para traduzir ao idioma de destino.\n",
    "É definido o `forced_bos_token_id` como `en` no método `generate` para traduzir ao inglês."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Do not interfere with the matters of the witches, because they are delicate and will soon be angry.'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "generated_tokens = model.generate(**encoded_zh, forced_bos_token_id=tokenizer.get_lang_id(\"en\"))\n",
    "tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## MBart"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Os seguintes modelos do MBart podem ser utilizados para tradução multilinguística:\n",
    "\n",
    "- `facebook/mbart-large-50-one-to-many-mmt` (Tradução automática multilinguística de um a vários, 50 idiomas)\n",
    "- `facebook/mbart-large-50-many-to-many-mmt` (Tradução automática multilinguística de vários a vários, 50 idiomas)\n",
    "- `facebook/mbart-large-50-many-to-one-mmt` (Tradução automática multilinguística vários a um, 50 idiomas)\n",
    "- `facebook/mbart-large-50` (Tradução multilinguística, 50 idiomas)\n",
    "- `facebook/mbart-large-cc25`\n",
    "\n",
    "Neste exemplo, carrega-se o checkpoint `facebook/mbart-large-50-many-to-many-mmt` para traduzir do finlandês ao inglês.\n",
    "Pode-se definir o idioma de origem no tokenizador:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import AutoTokenizer, AutoModelForSeq2SeqLM\n",
    "\n",
    "en_text = \"Do not meddle in the affairs of wizards, for they are subtle and quick to anger.\"\n",
    "fi_text = \"Älä sekaannu velhojen asioihin, sillä ne ovat hienovaraisia ja nopeasti vihaisia.\"\n",
    "\n",
    "tokenizer = AutoTokenizer.from_pretrained(\"facebook/mbart-large-50-many-to-many-mmt\", src_lang=\"fi_FI\")\n",
    "model = AutoModelForSeq2SeqLM.from_pretrained(\"facebook/mbart-large-50-many-to-many-mmt\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tokenizando o texto:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "encoded_en = tokenizer(en_text, return_tensors=\"pt\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "O MBart força o id do idioma de destino como o primeiro token gerado para traduzir ao idioma de destino.\n",
    "É definido o `forced_bos_token_id` como `en` no método `generate` para traduzir ao inglês."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"Don't interfere with the wizard's affairs, because they are subtle, will soon get angry.\""
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "generated_tokens = model.generate(**encoded_en, forced_bos_token_id=tokenizer.lang_code_to_id(\"en_XX\"))\n",
    "tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Se estiver usando o checkpoint `facebook/mbart-large-50-many-to-one-mmt` não será necessário forçar o id do idioma de destino\n",
    "como sendo o primeiro token generado, caso contrário a usagem é a mesma."
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 4
}
